use gtk::glib;
use gtk::prelude::*;
use gtk::subclass::prelude::ObjectSubclassIsExt;

use crate::ui::chat_record_item::RecordItem;

glib::wrapper! {
    pub struct ChatRecordListView(ObjectSubclass<imp::ChatRecordListView>)
        @extends adw::Bin, gtk::Widget,
        @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget;
}

impl ChatRecordListView {
    pub fn new() -> Self {
        glib::Object::new::<Self>()
    }

    /// 添加一个新的 RecordItem 到列表
    pub fn append(&self, item: &RecordItem) {
        let imp = self.imp();
        let list_store = imp.list_store.get().expect("list_store not initialized");
        list_store.append(item);

        let self_clone = self.clone();
        let item_clone = item.clone();
        item.connect_request_delete(move || {
            log::warn!("Received `request-delete` signal. Delete this RecordItem.");
            self_clone.remove_item(&item_clone);
        });
    }

    /// 在指定位置插入 RecordItem
    pub fn insert(&self, position: u32, item: &RecordItem) {
        let imp = self.imp();
        let list_store = imp.list_store.get().expect("list_store not initialized");
        list_store.insert(position, item);
    }

    /// 移除指定位置的 RecordItem
    pub fn remove(&self, position: u32) {
        let imp = self.imp();
        let list_store = imp.list_store.get().expect("list_store not initialized");
        list_store.remove(position);
    }

    /// 获取列表中的项目数量
    pub fn len(&self) -> u32 {
        let imp = self.imp();
        let list_store = imp.list_store.get().expect("list_store not initialized");
        list_store.n_items()
    }

    /// 检查列表是否为空
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// 获取指定位置的 RecordItem
    pub fn item(&self, position: u32) -> Option<RecordItem> {
        let imp = self.imp();
        let list_store = imp.list_store.get().expect("list_store not initialized");
        list_store.item(position).and_downcast()
    }

    /// 根据 RecordItem 对象删除项目
    pub fn remove_item(&self, item: &RecordItem) -> bool {
        let imp = self.imp();
        let list_store = imp.list_store.get().expect("list_store not initialized");

        let mut found = false;

        // 遍历列表查找匹配的项目
        for i in 0..list_store.n_items() {
            if let Some(list_item) = list_store.item(i).and_downcast::<RecordItem>() {
                if list_item == item.clone() {
                    list_store.remove(i);
                    found = true;
                }
            }
        }

        return found;
    }

    /// 清空所有项目
    pub fn clear(&self) {
        let imp = self.imp();
        let list_store = imp.list_store.get().expect("list_store not initialized");
        list_store.remove_all();
    }
}

mod imp {
    use std::cell::RefCell;
    use std::sync::OnceLock;

    use crate::ui::chat_record_item::RecordItem;

    use super::*;
    use adw::prelude::*;
    use adw::subclass::bin::BinImpl;
    use gtk::glib;
    use gtk::subclass::prelude::*;

    #[derive(Default)]
    pub struct ChatRecordListView {
        // Add fields here
        /// Contains child items.
        pub(super) scroll_window: gtk::ScrolledWindow,
        pub(super) list_view: gtk::ListView,
        pub(super) selection_model: RefCell<Option<gtk::SingleSelection>>,
        pub(super) list_store: OnceLock<gtk::gio::ListStore>,
    }

    #[glib::object_subclass]
    impl ObjectSubclass for ChatRecordListView {
        const NAME: &'static str = "ChatRecordListView";
        type Type = super::ChatRecordListView;
        type ParentType = adw::Bin;
    }

    impl ObjectImpl for ChatRecordListView {
        fn constructed(&self) {
            self.parent_constructed();

            let obj = self.obj();

            // 设置滚动窗口
            self.scroll_window.set_vexpand(true);
            self.scroll_window.set_hexpand(true);
            self.scroll_window.set_child(Some(&self.list_view));

            // 设置选择模型
            let list_store = self
                .list_store
                .get_or_init(|| gtk::gio::ListStore::new::<RecordItem>());
            let selection_model = gtk::SingleSelection::new(Some(list_store.clone()));
            *self.selection_model.borrow_mut() = Some(selection_model.clone());
            self.list_view.set_model(Some(&selection_model));

            // 设置工厂来创建列表项
            let factory = gtk::SignalListItemFactory::new();
            self.list_view.set_factory(Some(&factory));

            // Setup: 为每个列表项创建 UI
            factory.connect_setup(|_, list_item| {
                let list_item = list_item.downcast_ref::<gtk::ListItem>().unwrap();
                // 这里我们直接使用 RecordItem 作为列表项的子部件
                // 因为 RecordItem 本身就是一个完整的部件
                let record_item = RecordItem::new("");
                list_item.set_child(Some(&record_item));
            });

            // Bind: 为每个列表项设置数据
            factory.connect_bind(|_, list_item| {
                let list_item = list_item.downcast_ref::<gtk::ListItem>().unwrap();
                log::trace!("Bind called for list item");

                // `.child()` returns the current child widget of the `self.list_view`.
                let record_item = list_item.child().and_downcast::<RecordItem>().unwrap();
                log::trace!("Successfully downcast child to RecordItem");

                // `.item()` returns the corresponding item from self::list_store (IsA<gio::ListModel>).
                let list_item = list_item.item().and_downcast::<RecordItem>().unwrap();
                log::trace!("Successfully downcast item to RecordItem");

                // 这里可以设置 RecordItem 的属性
                // 例如：复制标签文本等
                let label = list_item.label();
                log::trace!("Setting label to: {}", label);
                record_item.set_label(&label);

                // 连接删除信号
                let item_clone = list_item.clone();
                record_item.connect_confirm_delete(move || {
                    log::warn!("Received `confirm-delete` signal in factory bind");
                    item_clone.emit_by_name::<()>("request-delete", &[]);
                });
            });

            // 设置滚动窗口作为 Bin 的子部件
            obj.set_child(Some(&self.scroll_window));
        }
    }

    impl WidgetImpl for ChatRecordListView {}

    impl BinImpl for ChatRecordListView {}
}
